// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: DServer support simple entity
// feature: modify log level
// feature: Unified Transport Abstraction Layer Unified Transport Abstraction Layer
// feature: support batch send
// ------------------------------------------------------------------

#ifndef SRC_CPP_RTPS_TRANSPORT_RAWCHANNELRESOURCE_H_
#define SRC_CPP_RTPS_TRANSPORT_RAWCHANNELRESOURCE_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <linux/if_packet.h>
#include <arpa/inet.h>
#include <linux/filter.h>

#include <ertps/utils/LocatorAlias.h>
#include <transport/ChannelResource.h>

namespace vbs {
namespace transport {

class ReceiverResource;
class RAWTransport;

class RAWChannelResource : public ChannelResource {
 public:
    RAWChannelResource(uint32_t maxMsgSize, const vbsutil::xmlparser::Locator_t& locator, const std::string& sInterface,
                       std::shared_ptr<ReceiverResource> receiver);

    ~RAWChannelResource() override;

    inline uint32_t get_socket() { return socket_; }

    inline void set_socket(int sock) { socket_ = sock; }

    inline void interface(const std::string& interface) { interface_ = interface; }

    inline const std::string& interface() const { return interface_; }

    inline void message_receiver(std::shared_ptr<ReceiverResource> receiver) {
        message_receiver_ = std::move(receiver);
    }

    inline ReceiverResource* message_receiver() { return message_receiver_.get(); }

    inline void disable() override { ChannelResource::disable(); }

    void release();

 protected:
    /**
     * Blocking Receive from the specified channel.
     * @param receive_buffer vector with enough capacity (not size) to accomodate a full receive buffer. That
     * capacity must not be less than the receive_buffer_size supplied to this class during construction.
     * @param receive_buffer_capacity Maximum size of the receive_buffer.
     * @param[out] receive_buffer_size Size of the received buffer.
     * @param[out] remote_locator Locator describing the remote restination we received a packet from.
     */
    bool Receive(unsigned char* receive_buffer, uint32_t receive_buffer_capacity, uint32_t& receive_buffer_size,
                 vbsutil::xmlparser::Locator_t& remote_locator, vbsutil::xmlparser::Locator_t& local_locator);

    /**
     * Function to be called from a new thread, which takes cares of performing a blocking receive
     * operation on the ReceiveResource
     * @param input_locator - Locator that triggered the creation of the resource
     * @param thread_name - thread name
     */
    void perform_listen_operation(vbsutil::xmlparser::Locator_t input_locator, const std::string& thread_name);

 private:
    std::shared_ptr<ReceiverResource> message_receiver_;  // Associated Readers/Writers inside of MessageReceiver
    uint32_t socket_;
    std::string interface_;

    RAWChannelResource(const RAWChannelResource&) = delete;
    RAWChannelResource& operator=(const RAWChannelResource&) = delete;
};

}  // namespace transport
}  // namespace vbs

#endif  // SRC_CPP_RTPS_TRANSPORT_RAWCHANNELRESOURCE_H_
